﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace NFinal.Collections
{
    /// <summary>
    /// 获取字典的值的代理
    /// </summary>
    /// <typeparam name="TValue"></typeparam>
    /// <typeparam name="TParam"></typeparam>
    /// <param name="param"></param>
    /// <returns></returns>
    public delegate TValue GetDictionaryValue<TValue,TParam>(TParam param);
    /// <summary>
    /// 多线程的快速字典类
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class FastAsyncDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        private FastDictionary<TKey, TValue> innerDictionary = null;
        private ReaderWriterLockSlim readWriteLock;
        private const int timeout = 1000;
        /// <summary>
        /// 多线程的获取和生成value值,适用于生成value值比较耗时的操作
        /// </summary>
        /// <typeparam name="TParam"></typeparam>
        /// <param name="key"></param>
        /// <param name="getValueDelegate"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public TValue GetOrAddValue<TParam>(TKey key, GetDictionaryValue<TValue, TParam> getValueDelegate,TParam param)
        {
            TValue value = default(TValue);
            readWriteLock.EnterWriteLock();
            try
            {
                if (!innerDictionary.TryGetValue(key, out value))
                {
                    value = getValueDelegate(param);
                    innerDictionary[key] = value;
                }
            }
            finally
            {
                readWriteLock.ExitWriteLock();
            }
            return value;
        }
        /// <summary>
        /// 元素访问
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TValue this[TKey key]
        {
            get {
                if (readWriteLock.TryEnterReadLock(timeout))
                {
                    TValue val= innerDictionary[key];
                    readWriteLock.ExitReadLock();
                    return val;
                }
                return default(TValue);
            }
            set
            {
                if (readWriteLock.TryEnterWriteLock(timeout))
                {
                    innerDictionary[key] = value;
                    readWriteLock.ExitWriteLock();
                }
            }
        }
        public FastAsyncDictionary(IEqualityComparer<TKey> comparer)
        {
            this.innerDictionary = new FastDictionary<TKey, TValue>(comparer);
            this.readWriteLock = new ReaderWriterLockSlim();
        }
        /// <summary>
        /// 字典初始化
        /// </summary>
        public FastAsyncDictionary()
        {
            this.innerDictionary = new FastDictionary<TKey, TValue>();
            this.readWriteLock = new ReaderWriterLockSlim();
        }
        /// <summary>
        /// 添加元素
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(TKey key, TValue value)
        {
            if (readWriteLock.TryEnterWriteLock(timeout))
            {
                this.innerDictionary[key] = value;
                readWriteLock.ExitWriteLock();
            }
        }
        /// <summary>
        /// 清除所有元素
        /// </summary>
        public void Clear()
        {
            if (readWriteLock.TryEnterWriteLock(timeout))
            {
                this.innerDictionary.Clear();
                readWriteLock.ExitWriteLock();
            }
        }
        /// <summary>
        /// 查找元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Contains(TKey key)
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                bool result= this.innerDictionary.Contains(key);
                readWriteLock.ExitReadLock();
                return result;
            }
            return false;
        }
        /// <summary>
        /// 查找元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(TKey key)
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                bool result= this.innerDictionary.Contains(key);
                readWriteLock.ExitReadLock();
                return result;
            }
            return false;
        }
        /// <summary>
        /// 查找元素
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool ContainsValue(TValue value)
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                bool result = this.innerDictionary.ContainsValue(value);
                readWriteLock.ExitReadLock();
                return result;
            }
            return false;
        }
        /// <summary>
        /// 获取元素
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                bool result = this.innerDictionary.TryGetValue(key, out value);
                readWriteLock.ExitReadLock();
                return result;
            }
            value = default(TValue);
            return false;
        }
        /// <summary>
        /// 元素数量
        /// </summary>
        public int Count
        {
            get
            {
                if (readWriteLock.TryEnterReadLock(timeout))
                {
                    int count = this.innerDictionary.Count;
                    readWriteLock.ExitReadLock();
                    return count;
                }
                return -1;
            }
        }
        /// <summary>
        /// 移除元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(TKey key)
        {
            if (readWriteLock.TryEnterWriteLock(timeout))
            {
                bool result = this.innerDictionary.Remove(key);
                readWriteLock.ExitWriteLock();
                return result;
            }
            return false;
        }
        /// <summary>
        /// 复制元素
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                this.innerDictionary.CopyTo(array, index);
                readWriteLock.ExitReadLock();
            }
        }
        public int Capacity
        {
            get
            {
                return this.innerDictionary.Capacity;
            }
        }
        public IEqualityComparer<TKey> Comparer
        {
            get
            {
                return this.innerDictionary.Comparer;
            }
        }
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                IEnumerator<KeyValuePair<TKey, TValue>> enumerator= this.innerDictionary.GetEnumerator();
                readWriteLock.ExitReadLock();
                return enumerator;
            }
            return null;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            if (readWriteLock.TryEnterReadLock(timeout))
            {
                IEnumerator enumerator = this.innerDictionary.GetEnumerator();
                readWriteLock.ExitReadLock();
                return enumerator;
            }
            return null;
        }
        /// <summary>
        /// 析构释放对象时，把读写锁释放掉
        /// </summary>
        ~FastAsyncDictionary()
        {
            if (readWriteLock != null) readWriteLock.Dispose();
        }
    }
}
